//MyTime.cpp
#include "MyTime.h"
#include <ctime>

using std::ostream;


// CONSTRUCTORS
      // Default (explicit)
MyTime::MyTime()
{
	_hours = 0;
	_minutes = 0;
	_seconds = 0;
	_ticks = 0;
}

 // Copy
MyTime::MyTime(const MyTime &origMyTime)
{
	_hours = origMyTime._hours;
	_minutes = origMyTime._minutes;
	_seconds = origMyTime._seconds;
	_ticks = origMyTime._ticks;
}

 // Parameterized (various useful overloads)
            // Hours, Minutes, Seconds, Miliseconds
MyTime::MyTime(int initHrs, int initMins, int initSecs, int initMilisecs)
{
	_hours = _ticksPerHour * initHrs;
	_minutes = _ticksPerMinute * initMins;
	_seconds = _ticksPerSecond * initSecs;
	_ticks = initMilisecs;
	_ticks = _ticks + _hours + _minutes + _seconds;
}

       // Hours, Minutes, Seconds
MyTime::MyTime(int initHrs, int initMins, int initSecs)
{
	_hours = _ticksPerHour * initHrs;
	_minutes = _ticksPerMinute * initMins;
	_seconds = _ticksPerSecond * initSecs;
	_ticks = _hours + _minutes + _seconds;
}

       // Hours, Minutes
MyTime::MyTime(int initHrs, int initMins)
{
	_hours = _ticksPerHour * initHrs;
	_minutes = _ticksPerMinute * initMins;
	_seconds = 0;
	_ticks = _hours + _minutes;
}

      // Ticks
MyTime::MyTime(long initTicks)
{
	_hours = 0;
	_minutes = 0;
	_seconds = 0;
	_ticks = initTicks;
}

// DESTRUCTOR
MyTime::~MyTime()
{

}

// METHODS
      // Accessors and mutators for:
      // hours, minutes, seconds, ticks
int MyTime::GetHours() const
{
	const int hours = (_hours / _ticksPerHour);	 
	return hours;
}

void MyTime::SetHours(int newHours)
{
	_ticks -=_hours;
	_hours = newHours * _ticksPerHour;
	_ticks += _hours;
}

int MyTime::GetMinutes() const
{
	const int minutes = (_minutes / _ticksPerHour);
	return minutes;
}

void MyTime::SetMinutes(int newMinutes)
{
	_ticks -= _minutes;
	_minutes = newMinutes * _ticksPerMinute;
	_ticks += _minutes;
}

int MyTime::GetSeconds() const
{
	const int seconds = (_seconds / _ticksPerSecond);
	return seconds;
}

void MyTime::SetSeconds(int newSeconds)
{
	_ticks -= _seconds;
	_seconds = newSeconds * _ticksPerSecond;
	_ticks += _seconds;
}

long MyTime::GetTicks() const
{
	return _ticks;
}

void MyTime::SetTicks(int newTicks)
{
	long hourRemainder;
	long minuteRemainder;
	long secondRemainder;

	_ticks = newTicks;
	_hours = _ticks / _ticksPerHour;
	_hours = _hours * _ticksPerHour;
	hourRemainder = _ticks % _ticksPerHour;
	_minutes = hourRemainder / _ticksPerMinute;
	_minutes = _minutes * _ticksPerMinute;
	minuteRemainder = hourRemainder % _ticksPerMinute;
	_seconds = minuteRemainder / _ticksPerSecond;
	_seconds = _seconds * _ticksPerSecond;
	secondRemainder = minuteRemainder % _ticksPerSecond;
}

// SetTime (various useful overloads)
            // Hours, Minutes, Seconds, Miliseconds
void MyTime::SetTime(int newHrs, int newMins, int newSecs, int newMilisecs)
{
	_hours = newHrs * _ticksPerHour;
	_minutes = newMins * _ticksPerMinute;
	_seconds = newSecs * _ticksPerSecond;
	_ticks = newMilisecs;
	_ticks = _ticks + _hours + _minutes + _seconds;
}

// Hours, Minutes, Seconds
void MyTime::SetTime(int newHrs, int newMins, int newSecs)
{
	_hours = _ticksPerHour * newHrs;
	_minutes = _ticksPerMinute * newMins;
	_seconds = _ticksPerSecond * newSecs;
	_ticks = _hours + _minutes + _seconds;
}

// Hours, Minutes
void MyTime::SetTime(int newHrs, int newMins)
{
	_hours = _ticksPerHour * newHrs;
	_minutes = _ticksPerMinute * newMins;
	_ticks = _hours + _minutes + _seconds;
}

// Ticks
void MyTime::SetTime(long newTicks)
{
	this ->SetTicks(newTicks);
}

// MyTime
void MyTime::SetTime(const MyTime & aMyTime)
{
	_hours = aMyTime._hours;
	_minutes = aMyTime._minutes;
	_seconds = aMyTime._seconds;
	_ticks = aMyTime._ticks;
}

// Now
// a static function that returns a MyTime object
//   initialized to the current time according to the system cloc
MyTime MyTime::Now()
{
	time_t rawtime;
    
  struct tm * timeinfo;

  time ( &rawtime );
  timeinfo = localtime ( &rawtime );
  asctime (timeinfo);

  MyTime testTime(timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
  return testTime;
}

      // Add (various useful methods)
      // For adding amounts of time to this MyTime
            // Hours
void MyTime::AddHours(int moreHours)
{
	_ticks -= _hours;
	int hours = _hours / _ticksPerHour;
	hours += moreHours;
	if (hours >= 24)
	{
		do
			hours -= 24;
		while (hours >= 24);
	}
	_hours = _ticksPerHour * hours;
	_ticks += _hours;

	
	
}

// Minutes
void MyTime::AddMinutes(int moreMinutes)
{
	_ticks -= _minutes;
	_ticks -= _hours;
	int minutes = _minutes / _ticksPerMinute;
	int hours = _hours / _ticksPerHour;
	minutes += moreMinutes;
	while (minutes >= 60)
	{
			minutes -= 60;
			hours += 1;
	}

	_minutes = _ticksPerMinute * minutes;
	_hours = _ticksPerHour * hours;
	_ticks = _minutes + _hours;
}

// Seconds
void MyTime::AddSeconds(long moreSeconds)
{
	_ticks -= _seconds;
	_ticks -= _minutes;
	_ticks -= _hours;
	int seconds = _seconds / _ticksPerSecond;
	int minutes = _minutes / _ticksPerMinute;
	int hours = _hours / _ticksPerHour;
	seconds += moreSeconds;
	while (seconds >= 60)
	{
	seconds -= 1;
	minutes += 1;
	}
	if (minutes >= 60)
	{
		hours += 1;
		minutes -= 60;
	}
	
	_seconds = _ticksPerSecond * seconds;
	_minutes = _ticksPerMinute * minutes;
	_hours = _ticksPerHour * hours;
	_ticks = _seconds + _minutes + _hours;
}

// Ticks
void MyTime::AddTicks(long moreTicks)
{
	_ticks += moreTicks;
	this->SetTicks(_ticks);
}

// MyTime
void MyTime::AddTime(const MyTime & aMyTime)
{
	_ticks += aMyTime._ticks;
	this->SetTicks(_ticks);
}

// Compare
      // Takes a MyTime argument
      // Returns (zero) if the argument has the same time as this MyTime
      // Returns (a positive int)  if the argument is before this MyTime
      // Returns (a negative int)  if the argument is after this MyTime
int MyTime::Compare(const MyTime & aMyTime) const
{
	const long ticks = ( _ticks - aMyTime._ticks);	
	return ticks;
}

// Equals
      // Takes a MyTime argument
      // Returns (true) if the argument has the same time
	  //   as this MyTime, otherwise it returns (false).
bool MyTime::Equals(const MyTime & aMyTime) const
{	
	const long ticks1 = _ticks;
	const long ticks2 = aMyTime._ticks;
	if (ticks1 == ticks2)
		return true;
	else
		return false;
}

 // Subtract (various useful methods)
      // For subtracting amounts of time to this MyTime
            // Hours
void MyTime::SubtractHours(int lessHours)
{
	_ticks -= _hours;
	int hours = _hours / _ticksPerHour;
	hours -= lessHours;
	_hours = _ticksPerHour * hours;
	_ticks += _hours;
}

            // Minutes
void MyTime::SubtractMinutes(int lessMinutes)
{
	_ticks -= _minutes;
	int minutes = _minutes / _ticksPerMinute;
	minutes -= lessMinutes;
	_minutes = _ticksPerMinute * minutes;
	_ticks += _minutes;
}

            // Seconds
void MyTime::SubtractSeconds(long lessSeconds)
{
	_ticks -= _seconds;
	int seconds = _seconds / _ticksPerSecond;
	seconds -= lessSeconds;
	_seconds = _ticksPerSecond * seconds;
	_ticks += _seconds;
}

            // Ticks
void MyTime::SubtractTicks(long lessTicks)
{
	_ticks -= lessTicks;
	this->SetTicks(_ticks);
}

            // MyTime
void MyTime::SubtractTime(const MyTime & aMyTime)
{
	_ticks -= aMyTime._ticks;
	this->SetTicks(_ticks);
}

// OVERLOADED OPERATORS
      // = (assignment - takes a MyTime)
MyTime MyTime::operator= (const MyTime & aMyTime)
{
	this->SetTime(aMyTime);
	return aMyTime;
}

      // +, += (Addition - takes a MyTime)
MyTime MyTime::operator+ (const MyTime & aMyTime) const
{
	MyTime tempTime(_ticks);
	tempTime.AddTime(aMyTime);
	return tempTime;
}

MyTime MyTime::operator+= (const MyTime & aMyTime)
{
	MyTime tempTime(_ticks);
	tempTime.AddTime(aMyTime);
	this->SetTime(tempTime);
	return tempTime;
}

// >, <, >=, <=, ==, != (boolean relational test operators)
bool MyTime::operator> (const MyTime & aMyTime) const 
{
	if (this->Compare(aMyTime) > 0)
		return true;
	else 
		return false;

}

bool MyTime::operator< (const MyTime & aMyTime) const 
{
if (this->Compare(aMyTime) < 0)
		return true;
	else 
		return false;
}

bool MyTime::operator>= (const MyTime & aMyTime) const 
{
if (this->Compare(aMyTime) >= 0)
		return true;
	else 
		return false;
}

bool MyTime::operator<= (const MyTime & aMyTime) const
{
if (this->Compare(aMyTime) <= 0)
		return true;
	else 
		return false;
}

bool MyTime::operator== (const MyTime & aMyTime) const
{
	if (this->Equals(aMyTime) == true)
		return true;
	else 
		return false;
}

bool MyTime::operator!= (const MyTime & aMyTime) const 
{
	if (this->Equals(aMyTime) == false)
		return true;
	else 
		return false;
}

// <<, >> stream insertion and extraction
ostream & operator<< (ostream & os, const MyTime & aMyTime)
{
	int hours = aMyTime._hours / aMyTime._ticksPerHour;
	int minutes = aMyTime._minutes / aMyTime._ticksPerMinute;
	int seconds = aMyTime._seconds / aMyTime._ticksPerSecond;

	std::cout << hours << ":" << minutes;
	return os;
}

istream & operator>> (istream & is, MyTime & aMyTime)
{
	std::cin >> aMyTime._ticks;
	return is;
}